home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
comm
/
maxshell.lha
/
MAXShell.c
< prev
next >
Wrap
Text File
|
1995-08-28
|
32KB
|
1,100 lines
/*
MAXShell v1.0 - A door for running CLI based programs under M A X's BBS
~~~~~~~~~~~~~
Based on TrShell, by Timothy Aston. Max's adaption by MPS '95!
At last! Now Max's sysops can access a FULL remote CLI and access the
huge range of CLI based doors available, such as Hack & Slash, Global
War 2, and Contris!
This door is pretty much a conversion of the original TAShell for
TransAmiga BBS, by Timothy Aston (Which used much of the remote CLI
code from the FIFO distribution), to a Max's compatible door. Extra
Max's specific functionality has also been added.
To run this door, you will need Matthew Dillon's 'fifo.library' and
'fifo-handler' installed. Just copy the included 'fifo.library' to
libs: and 'fifo-handler' to l:, then add 'run >nil: <nil: l:fifo-handler'
to your user-startup.
Run like any other door (Function 34), and use the following arguments:
Usage: MAXShell [<startup-script>] [-c] [-d] [-e] [-f]
~~~~~~ [-s<substitution char>] [-t]
Where: <startup-script> is an optional shell startup script. Use this for
running games, etc. An example startup script could be:
-----------------------------CUT HERE-----------------------------
cd doors:globalwar
globalwar %f ACCESS %l PAGELENGTH %p TIMELEFT %k
endcli
-----------------------------CUT HERE-----------------------------
Max's autoinserts can be used in the script for supplying needed
parameters to shell programs. (For example, the above will supply
the user name to Global War, as needed).
Note the ENDCLI - This is very important, or users will exit to
the shell after quitting Global War!
Also note that all scripts must be in BBS:MAXSHELL/, and you
obviously don't supply the path for this reason. The reason I
did this was Max's Filename/Name/Dest/Path firld doesn't have
much room, so this will save characters!
If a startup script filename isn't supplied, MAXShell will just
give a shell...
-c is a switch to filter out ^C's from the user. Same goes for
the -d, -e and -f.
You should always have -c and -d enabled, or users can break out
of the startup script if they're quick enough, and enter CLI!
-s<substitution char> is a switch to enable an additional
conversion to the user name (%f). The supplied character will
replace spaces in the user name. This prevents problems with
command line parsing and spaces in certain programs. I suppose
you could have used "%f" instead of %f in the script, but it's
there if you want the feature!
-t is a switch to enable an additional conversion to the user's
remaining time (%k). The time value will me made to be 5 minutes
lower. This will allow the CLI based program to exit (Based on
this time limit) before the BBS will hang up, avoiding problems.
Of course, this is only useful if the program supports time limits
in the first place!
(The usage is also shown when MAXShell isn't run as a door, ie. run from
the CLI).
Examples on BBS use of MAXShell:
Global War 2: (Assuning above example gw-startup is in DOORS:MAXSHELL/)
Key: Function: Extra: Lo acc: Hi acc:
G 34 0 10 10000
Filename/Name/Dest/Path:
DOORS:MAXSHELL/MAXSHELL GW-STARTUP -c -d -s_ -t
Standard CLI:
Key: Function: Extra: Lo acc: Hi acc: Filename/Name/Dest/Path:
! 34 0 10000 10000 DOORS:MAXSHELL/MAXSHELL
Notes: * Make sure you have a standard AmigaDOS shell (I had ZShell
~~~~~~ in my shell-startup, but will not work with FIFO: as far as
I could see (In other words, the computer came up with some
alert, and after I removed 'zsh' from my shell-startup, it
didn't happen again!)
* Yep, that bug mentioned below does occur in my conversion,
and, yep, you guessed it, I haven't got the faintest clue
on why it occurs. The solution is to use a different FIFO
every time by creating the FIFO name via something like
time() to make it unique every time a new one is opened!
This is what I did in converting, and what was originally
done in the TA scripts that invoked TaShell...
* If a user drops carrier, the program simply sends a ^C to
the FIFO shell, and exits. This is not always sufficient to
stop the running shell program. MAXShell will return
correctly, but the shell process will still be left running.
This caused complications with the temporary shell-startup
script I use (With the converted Max's auto-inserts), as it
will still be in use (By the non-exiting shell), and thus
can't be removed or changed (Which I needed to do: when
another user accesses the door, the converted script must
reflect the new username). A similar workaround was used as
above to make a unique temporary filename every time. Don't
worry about about RAM: filling up though, the problem only
occurs when someone hangs up, or you twit the user. (And even
then, only in certain cases). One 'locked-out' file occurs
for each lost-carrier/twit. (Again, only in certain cases).
This problem exists in the original TaShell also... If anyone
knows a better way of handling this I'd like to know!
* Max's special conversion characters (@, |, %) are not
supported at this time - They were causing many problems,
so they are printed verbatim. If you want to have support
them, you can always have a go at modifying this source
code! % should be reasonably easy to get working
properly. The only precaution is to make sure that the
program handles the %<char> across a 'split' between
blocks of output to the Max's screen... This has been
implemented for escape codes already.
* Another wierd bug: The CLI process number below MAXShell's
CLI will be suspended until MAXShell's CLI finishes. God
knows why, it doesn't seem to harm anything, so I can't be
bothered figuring this one out! Of course, as above, you
could always try...
* Finally, the user's PAUSE flag is set to OFF during the
duration of the door (To stop games like Hack & Slash having
annoying 'Press Return...' prompts every screenfull of text),
and returned to the user's original setting before exiting to
the BBS. The PAUSE flag will stay OFF, if the user hangs up or
is twitted.
Contact: For whatever reason, contact me via e-mail: mp@deakin.edu.au, or
~~~~~~~~ call my BBS (See BBS advertisement below).
Finally: This program is hereby FREEWARE! You need not pay for it, as
~~~~~~~~ it's just something I hacked up to add a much needed feature
to Max's BBS! Just be sure to distribute the files/archive as
is.
I'm curious why someone hasn't done this door for Max's BBS
before, as it was a pretty straightforward task even for me,
(Well, I DID have the TAShell source, I suppose...) and I'm
not what you'd call the best coder in the world, or the most
knowledgable Max's guy around! Which reminds me, I must thank
Greg Fitch for putting me on the right track about obtaining
Max's user values. Call his BBS: Xyonics on (07)808-4806.
I'm also (As you might have guessed!) distributing source as
well. I hope I start a trend in doing this, as I found it
difficult to find C source concerning Max's BBS, so would like
to pass on the knowledge I gained in doing this door. All I
ask is to credit me if you change the code, etc. and perhaps
a bit of extra access on your BBS and/or perhaps a free
registration of a shareware program you wrote.
Have fun with MAXShell!
Catch ya later,
MPS!
*/
/* Here is the original TrShell.c introduction:
TrShell, by Timothy Aston
This is put in the public domain as a simple example of how to use
transamiga.library with TransAmiga. This was written with DICE but
should easily be modified to other compilers. You should note however,
that DICE opens most libraries automatically (including fifo.library).
SAS users will probably have to generate #pragmas for
transamiga.library and fifo.library. fifo.h is included with the FIFO
distribution.
BTW: Note that there does seem to be a persistent bug in this, it
doesn't fully release the FIFO, any attempt to restart it with an
already used FIFO name causes NewShell to hang. If you can figure out
why this is, I'd really like to know.
*/
const char version[]="\0$VER: MAXShell 1.0 ("__DATE__")\0";
#include <clib/exec_protos.h>
#include <exec/exec.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <fcntl.h>
#include <libraries/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fifo.h"
#include "fifopr.h"
#include <proto/exec.h>
#include <proto/dos.h>
#include <time.h>
#define ESC 27
#define FF 12
char StrOut[255]; /* Output String! */
struct Library *FifoBase=NULL;
struct MsgPort *fifoport;
void *fifoR=NULL, *fifoW=NULL;
struct Message rmsg,wmsg;
char fifoname[30]="12345678901234567890123456789"; /* Name of FIFO */
char commandline[80]="NewShell FIFO:";
/* Command line for opening a FIFO: redirected CLI */
char newfile[30]="";
/* Filename for autoinsert-converted shell-startup */
char newchar=' '; /* Character used to replace spaces in user name */
char charbuf[100],txt[255];
char *fifoslav,*fifomast;
BOOL quit=FALSE;
BOOL readpending=FALSE, writepending=FALSE;
LONG n;
BOOL filterc=FALSE, filterd=FALSE, filtere=FALSE, filterf=FALSE, lesstime=FALSE;
void setup_fifo(void);
void shell_loop(void);
void Out(char *);
int InChar(void);
void SendBreak(char);
void check_fifo(void);
void OutLen(char * , ULONG);
void convert_lf(char * , char * , LONG);
void show_usage(void);
void close_all(void);
long getuserint(int);
void checkkey(char *);
void GetAutoInsert(char, char *);
void end(void);
void getsvar(int, char *);
void sendmessage(char[], int);
void hotkey(char[], char *);
void prompt(char[], char *, int);
void showfile(char[]);
void domenu(int, int, char *);
void changeuserint(int, long);
struct DoorMsg {
struct Message Door_Msg;
short command;
short data;
char string[80];
short carrier;
};
struct DoorMsg *doormsg, *garbage;
struct MsgPort *MyPort, *replyport;
struct Task *mytask; /* Pointer to this task so we can name it */
int err;
char linebuf[3000]=""; /* Line buffer */
time_t timeval; /* So we can get the time (For a different FIFO name */
time_t *timeptr; /* every time the door is run (Avoiding the closing bug) */
FILE *ifp, *ofp, *fopen();
/*
* end() - Notifies Paragon that we are done and ready to continue with
* the BBS. ALWAYS use this to exit from your program, or
* the BBS will go to never-never land.
*/
void end(void)
{
doormsg->command = 20;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
FreeMem(doormsg,(long)sizeof(*doormsg));
DeletePort(replyport);
exit(0);
}
/*
* getsvar(typ,mstring) - Gets certain string variables from Paragon.
* "mstring" is a pointer to a string to dump the string into. "typ" tells
* it what you want: 1=Name, 2=Password, 3=Address, 4=City, 5=State
* 6=Postal code, 7=Door pathname, 8=Default BBS pathname.
*/
/* Extra Max's values: 9: Date
10: Time
100: Phone number
101: Computer type
102: Comment (as defined by Sysop) */
void getsvar(typ,mstring)
int typ;
char *mstring;
{
doormsg->data = typ;
doormsg->command = 14;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
strcpy(mstring,doormsg->string);
(void)GetMsg(replyport);
}
/*
* sendmessage(mstring,nl) - Sends a message to the local window and to
* the modem (if applicable). "mstring" is the output string you want to
* send, "nl" is an integer which is 1 if you want it to send the
* c/r+l/f combination, or 0 if not.
*/
void
sendmessage(mstring,nl)
char mstring[];
int nl;
{
char newstr[100];
int i, ii=0;
doormsg->data = nl;
doormsg->command = 1;
/* Strip out some unwanted escape codes. (What the hell do the <ESC>[ p
escape codes do anyway? This sloppy code just makes things like Contris
look better rather than having strange [ p's showing up in places) */
for(i=0; i<strlen(mstring); i++)
{
newstr[ii]=mstring[i];
if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+3]==' '
&& mstring[i+4]=='p')
{
ii--;
i+=4;
}
else if(newstr[ii]=='\033' && mstring[i+1]=='[' && mstring[i+2]==' '
&& mstring[i+3]=='p')
{
ii--;
i+=3;
}
else if(newstr[ii]=='\033' && mstring[i+1]=='\033' && mstring[i+2]=='['
&& mstring[i+3]==' ' && mstring[i+4]=='p')
{
ii--;
i+=4;
}
else if(newstr[ii]=='\033' && mstring[i+1]=='\033' && mstring[i+2]=='['
&& mstring[i+4]==' ' && mstring[i+5]=='p')
{
ii--;
i+=5;
}
ii++;
}
newstr[ii]='\0';
strcpy(doormsg->string,newstr);
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
}
/*
* hotkey(mstring,ostring) - outputs the string "mstring" and waits
* for one key which it will place in element [0] of "ostring".
* "mstring" may be a null string, in which case it will only wait for
* the key, and not output any prompt.
*/
void
hotkey(mstring,ostring)
char mstring[];
char *ostring;
{
strcpy(doormsg->string,mstring);
doormsg->command = 8;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
strcpy(ostring,doormsg->string);
}
/*
* prompt(mstring,ostring,len) - outputs the string "mstring" and inputs
* a string which is placed in ostring. 'len' is the maximum number of
* characters which will be accepted.
*/
void
prompt(mstring,ostring,len)
char mstring[];
char *ostring;
int len;
{
strcpy(doormsg->string,mstring);
doormsg->data=len;
doormsg->command = 6;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
strcpy(ostring,doormsg->string);
}
/* showfile(mstring) shows the text file which mstring is the path to.
It handles ^C aborting, and ^S/^Q pausing. */
void
showfile(mstring)
char mstring[];
{
strcpy(doormsg->string,mstring);
doormsg->command = 10;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
}
/****************************************************
These two functions were added by
SWhite. MAX's BBS only!
****************************************************/
/* enter a menu function to execute 1-33 */
void
domenu(menu,extra,filename)
int menu,extra;
char *filename;
{
strcpy(doormsg->string,filename);
doormsg->command = menu+100;
doormsg->data = extra;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
}
/* Change user information 1-15:
0 NextEventMinutes
1 UserTimeRemaining
2 AccessLevel
3 TimeLeft
4 DL Ratio
5 Last Message Read
6 PageLength
7 NumCalls
8 UserMessages #
9 UserUpped Files
10 UserDownedFiles
11 LastDayOn
12 Last Minute On
13 UserConfig Flags ;Lower 2 Bytes
Flags, bits: 0-Rd, 1-Wr, 2-Up, 3-Dn, 4-Bltn, 5-ANSI
6-FSE, 7-Pause, 8-Cls, 9-Lck, 10-Get file
description, 11-Junk mail, 12-Allow File
Attaches
14 UserTimeBank
15 XFer Protocol
16 MaxTimeBank
*/
void
changeuserint(number,val)
int number;
long val;
{
long *ptr;
ptr = (long *)&doormsg->string; /* We need a long value not a ptr */
*ptr = val;
doormsg->command = 200;
doormsg->data = number;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
}
/* Get a piece of the user's integer information:
1: Access Level
2: Expert mode? (Paragon)
3: Net Credits? (paragon)
4: Number of calls
5: Calls to system
6: Graphics mode
7: Minutes remaining
8: Screen columns
9: Screen rows
100: Daily time limit
101: File ratio
102: Last message read (Updated when user logs off)
103: Messages posted
104: Files uploaded
105: Files downloaded
106: ?
107: ?
108: Flags (Binary bits)
+--------+------------+--------+---------------+
| FLAG | VALUE | FLAG | VALUE | Examples
+--------+------------+--------+---------------+ ~~~~~~~~
| Read | 1 (2^0) | Pause | 128 (2^7) | ALL ON : 8191
| Write | 2 (2^1) | CLS | 256 (2^8) | ALL OFF : 0
| Upld | 4 (2^2) | Lock | 512 (2^9) | Upld + Dnld : 12
| Dnld | 8 (2^3) | GFD | 1024 (2^10) | ANSI + FSE : 96
| Bltn | 16 (2^4) | Junk | 2048 (2^11) |
| ANSI | 32 (2^5) | AFA | 4096 (2^13) |
| FSE | 64 (2^6) | | |
+--------+------------+--------+---------------+
109: Amount in time bank
110: Protocol
111: Max time bank
*/
long getuserint(int val)
{
doormsg->command=13;
doormsg->data=val;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
return(doormsg->data);
}
/* Check for a key, without any waiting or prompting */
void CheckKey(char *ostring)
{
doormsg->command = 201;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
strcpy(ostring,doormsg->string);
}
/* Return Max's auto insert (And also replace spaces with defined
substitution character, in the full user name, if applicable) */
void GetAutoInsert(char istring, char *ostring)
{
int i;
doormsg->command = 203;
doormsg->data = istring;
PutMsg(MyPort,(struct Message *)doormsg);
(void)WaitPort(replyport);
(void)GetMsg(replyport);
strcpy(ostring,doormsg->string);
if(istring=='f')
{
for(i=0;i<strlen(ostring);i++)
{
if(ostring[i]==' ')
{
ostring[i]=newchar;
}
}
}
if(istring=='k' && lesstime==TRUE)
{
i=atoi(ostring);
i-=5;
if(i<0) i=0;
sprintf(ostring, "%d", i);
}
}
/* Setup FIFO, requires Dillon's fifo.library.
*/
void setup_fifo()
{
fifoslav = (char *) malloc(strlen(fifoname) + 16);
fifomast = (char *) malloc(strlen(fifoname) + 16);
sprintf(fifomast, "%s_m", fifoname);
sprintf(fifoslav, "%s_s", fifoname);
fifoport=CreatePort(NULL,0L);
fifoW = OpenFifo(fifomast, 2048, FIFOF_WRITE|FIFOF_NORMAL|FIFOF_NBIO);
if (fifoW == NULL)
{
printf("ERROR: Unable to open fifo %s\n", fifomast);
/* Temporary: I'll have to change this... */
exit(10);
}
fifoR = OpenFifo(fifoslav, 2048, FIFOF_READ|FIFOF_NORMAL|FIFOF_NBIO);
if (fifoR == NULL)
{
printf("ERROR: Unable to open fifo %s\n", fifoslav);
/* Temporary: I'll have to change this... */
exit(10);
}
rmsg.mn_ReplyPort = fifoport;
wmsg.mn_ReplyPort = fifoport;
}
/* The main shell loop.
*/
void shell_loop(void)
{
char c;
char outstr[100];
sprintf(outstr, "\r\nMAXShell v1.0\n\r\n");
Out(outstr);
RequestFifo(fifoR,&rmsg,FREQ_RPEND);
readpending=TRUE;
while (quit==FALSE)
{
c=InChar();
switch ( (int) c)
{
case 3:
if(filterc==FALSE) SendBreak('C');
break;
case 4:
if(filterd==FALSE) SendBreak('D');
break;
case 5:
if(filtere==FALSE) SendBreak('E');
break;
case 6:
if(filterf==FALSE) SendBreak('F');
break;
default:
n=WriteFifo(fifoW,&c,1);
if (n<1)
{
if (writepending==FALSE)
{
RequestFifo(fifoW,&wmsg,FREQ_RPEND);
writepending=TRUE;
}
}
break;
}
};
sendmessage(charbuf, 0); /* Flush the character buffer */
n=WriteFifo(fifoW,"\r",1);
if (n<1)
{
if (writepending==FALSE)
{
RequestFifo(fifoW,&wmsg,FREQ_RPEND);
writepending=TRUE;
}
}
}
/* Get a character, complete with carrier checks and rudimentry idle timer
* checking. Serial routines are smart enough to know whether or not
* serial I/O should place or not, so there's no need to check if this is
* a local logon or anything like that.
*/
int InChar()
{
ULONG l;
for (;;)
{
CheckKey(StrOut);
l=StrOut[0];
if (l)
return(StrOut[0]);
if (doormsg->carrier==1)
{
sprintf(txt,"%c[0;31m%cCarrier Lost.%c[37m\r\n",ESC,FF,ESC);
Out(txt);
SendBreak('C');
quit=TRUE;
return(0);
}
/* See if anything has come from out FIFO
*/
check_fifo();
if (quit==TRUE)
return(0);
/* Fix this crap later... (Don't think it's needed for Max's anyway!) */
/*
WaitTOF();
t++;
if (t>100000)
{
sprintf(txt,"%c[0;31m%cInactivity timeout.%c[37m\r\n",ESC,FF,ESC); Out(txt);
quit=TRUE;
SendBreak('C');
return(0);
}
*/
}
}
/* Check for something from FIFO.
*/
void check_fifo()
{
struct Message *msg;
char *ptr;
msg=GetMsg(fifoport);
if (msg==(struct Message *)&rmsg)
{
readpending=FALSE;
n=ReadFifo(fifoR,&ptr,0);
if (n>0)
{
/* These 2 values were 256, but changed them to this lower value to stop
the program crashing (Something to do with 80 character Max's lines?) */
if (n>40)
n=40;
OutLen(ptr,n);
n=ReadFifo(fifoR,&ptr,n);
}
if (n<0)
quit=TRUE;
else
{
RequestFifo(fifoR,&rmsg,FREQ_RPEND);
readpending=TRUE;
}
}
else if (msg==(struct Message *)&wmsg)
writepending=FALSE;
}
/* Text output to the serial device and the terminal window. The serial
* routines are smart enough to know whether serial I/O should take place
* or not, so its perfectly safe to always call them like this.
*/
void Out(char *str)
{
char temp[3000];
convert_lf(temp,str,strlen(str));
sendmessage(temp, 0);
}
void OutLen(char *str, ULONG len)
{
int counter, counter2, newlen, escape;
char temp[3000];
convert_lf(temp,str,len);
/* Check for a partial escape sequence at the end of the string, and save
it for the start of the next string, if required */
newlen=strlen(temp);
counter=newlen;
escape=FALSE;
while(counter>newlen-12 && counter>=0 && escape==FALSE)
{
if(temp[counter]=='\033')
{
escape=TRUE;
}
counter--;
}
counter2=counter;
counter2++;
while(counter2<newlen && escape==TRUE)
{
counter2++;
if((temp[counter2]>='A' && temp[counter2]<='Z')
|| (temp[counter2]>='a' && temp[counter2]<='z'))
{
escape=FALSE;
}
}
if(escape==TRUE)
{
strncat(charbuf, temp, counter);
/* sendmessage("->", 0); */
sendmessage(charbuf, 0);
/* sendmessage("<-", 0); */
strmid(temp, charbuf, counter+1, newlen-counter+1);
}
else
{
strcat(charbuf, temp);
/* sendmessage("=>", 0); */
sendmessage(charbuf, 0);
/* sendmessage("<=", 0); */
strcpy(charbuf, "");
}
}
/* Strip CR's from string, plus a few other conversions!
*/
void convert_lf(char *buf, char *str, LONG len)
{
LONG i, ii=0;
for (i=0; i<len; i++)
{
buf[ii]=str[i];
if(buf[ii]=='|')
{
buf[ii+1]='\013';
ii++;
}
if(buf[ii]=='@')
{
buf[ii+1]='\013';
ii++;
}
if(buf[ii]=='%')
{
buf[ii+1]='\013';
ii++;
}
if(buf[ii]=='\033')
{
buf[ii+1]='\033';
ii++;
}
if (buf[ii]=='\r')
{
ii--;
}
ii++;
}
buf[ii]='\0';
}
/* Display command line usage */
void show_usage(void)
{
printf("-- MAXShell v1.0 by MPS in 1995!\n");
printf("-- Based on the original TrShell by Tim Aston\n");
printf("-- M A X's BBS Remote Shell\n\n");
printf("Usage:\n\nMAXShell <startup-script> [-c] [-d] [-e] [-f] [-s<substitution char>] [-t]\n\n");
}
/* Send a break.
*/
void SendBreak(char c)
{
char buf[256];
LONG fh;
sprintf(buf, "FIFO:%s/%c", fifoname, c);
if (fh = Open(buf, 1005))
Close(fh);
}
/* Cleanly and safely shutdown all resources.
*/
void WaitMsg(struct Message *msg)
{
while (msg->mn_Node.ln_Type == NT_MESSAGE)
Wait(1 << msg->mn_ReplyPort->mp_SigBit);
Forbid();
Remove(&msg->mn_Node);
Permit();
}
main(int argc, char *argv[])
{
/* char userstring[1000]; */
char linein[256], lineout[256], linestring[80];
long uservalue, savedflags;
int i, ii, j;
char buffer[81],line_number;
char cportname[12]; /* ReplyPort and Control Port names */
char infilename[80]="DOORS:MAXSHELL/";
/* Pull out the line number from the argv field to find where we are */
line_number=argv[argc-1][0];
mytask=(struct Task *)FindTask('\0');
mytask->tc_Node.ln_Name = "DoorExample";
/* Create the Reply port, with the name based on the number... */
sprintf(buffer,"DoorReply%c",line_number);
replyport=(struct MsgPort *)CreatePort(buffer,0L);
doormsg=(struct DoorMsg *)AllocMem((long)sizeof(*doormsg),MEMF_PUBLIC);
if(doormsg==0)
{
puts("Couldn't allocate DoorMsg!");
show_usage();
return;
}
doormsg->Door_Msg.mn_Node.ln_Type = NT_MESSAGE;
doormsg->Door_Msg.mn_ReplyPort = replyport;
doormsg->Door_Msg.mn_Length = (UWORD)sizeof(*doormsg);
/* Locate the correct DoorControl port based on the line number */
sprintf(cportname,"DoorControl%c",line_number);
MyPort=(struct MsgPort *)FindPort(cportname);
if(MyPort==0L)
{
puts("DoorControl port not located!");
FreeMem(doormsg,(long)sizeof(*doormsg));
show_usage();
return;
}
/* Parse command line switch arguments.
*/
for (i=1; i<argc; i++)
{
if (argv[i][0]=='-')
{
switch (argv[i][1])
{
case 'c':
case 'C':
filterc=TRUE;
break;
case 'F':
case 'f':
filterf=TRUE;
break;
case 'D':
case 'd':
filterd=TRUE;
break;
case 'E':
case 'e':
filtere=TRUE;
break;
case 's':
case 'S':
newchar=argv[i][2];
break;
case 'T':
case 't':
lesstime=TRUE;
}
}
}
/* Open a CLI redirected to FIFO: based on an individual filename
generated from the system time (Hope it's not too long!) */
/* The same filename is also used for the names of the two FIFO's, opened
later */
timeval=time(timeptr);
sprintf(fifoname, "%d_%c", timeval, line_number);
strcat(commandline, fifoname);
strcat(commandline, "/rwkecs");
if(argc>2)
{
/* Generate a new Shell-Startup script with proper autoinserts
(Name is based on the same FIFO: filename used above) */
strcat(infilename, argv[1]);
ifp=fopen(infilename, "r");
if(ifp==NULL)
{
sendmessage("Can't open given startup script - Opening a standard shell.\r\n", 0);
}
else
{
sprintf(newfile,"RAM:%s", fifoname);
ofp=fopen(newfile, "w");
while(fgets(linein, 256, ifp)!=NULL)
{
ii=0;
for(i=0; i<strlen(linein);i++)
{
lineout[ii]=linein[i];
if(lineout[ii]=='%')
{
i++;
GetAutoInsert(linein[i], linestring);
for(j=0; j<strlen(linestring); j++)
{
lineout[ii]=linestring[j];
ii++;
}
ii--;
}
ii++;
}
lineout[ii]='\0';
fprintf(ofp, "%s", lineout);
}
fclose(ifp);
fclose(ofp);
/* ... and add the right stuff to the command line. */
strcat(commandline," FROM ");
strcat(commandline, newfile); /* Converted Shell-Startup script */
}
}
system(commandline);
/*
sendmessage(commandline,1);
sendmessage("\r\nHi there! Welcome to the test version of MAXShell\r\n",1);
uservalue=getuserint(1);
sprintf(userstring, "The user's flags value: %ld\n", uservalue);
sendmessage(userstring, 0);
hotkey("Press any key to (most likely) crash the computer...",buffer);
*/
/* Set user's PAUSE flag to OFF, so the annoying 'Press Return' doesn't appear
all the time in scrolling text doors such as Hack & Slash (And the standard
shell). The user's previous flag value is saved for restoration before
returning back to the BBS */
uservalue=getuserint(108);
savedflags=uservalue;
uservalue&=0xffffff7fL; /* Turn bit 7 (Pause) of the user's flags OFF */
changeuserint(13, uservalue);
/* Open fifo.library.
*/
FifoBase=OpenLibrary("fifo.library",0L);
if(!FifoBase)
{
printf("ERROR: Couldn't open fifo.library\n");
/* Temporary: I'll have to change this ... */
exit(10);
CloseLibrary(FifoBase);
}
setup_fifo();
shell_loop();
close_all();
/* Delete temporary shell-startup file... */
strcpy(linein, "c:delete ");
strcat(linein, newfile);
system(linein);
/* Restore user's previous PAUSE flag setting */
changeuserint(13, savedflags);
/* Close down the door... */
end();
}
void close_all(void)
{
if (readpending)
{
RequestFifo(fifoR, &rmsg, FREQ_ABORT);
WaitMsg(&rmsg);
}
if (writepending)
{
RequestFifo(fifoW, &wmsg, FREQ_ABORT);
WaitMsg(&wmsg);
}
if (fifoR) CloseFifo(fifoR, FIFOF_EOF);
if (fifoW) CloseFifo(fifoW, FIFOF_EOF);
if (fifoport) DeletePort(fifoport);
if (FifoBase) CloseLibrary(FifoBase);
}